package com.stedu.mall.orderservice.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.stedu.mall.common.bean.*;
import com.stedu.mall.common.exception.SteduException;
import com.stedu.mall.common.service.AddrService;
import com.stedu.mall.common.service.GoodsService;
import com.stedu.mall.common.service.OrderService;
import com.stedu.mall.common.service.UserService;
import com.stedu.mall.orderservice.mapper.CartMapper;
import com.stedu.mall.orderservice.mapper.OrderDetailMapper;
import com.stedu.mall.orderservice.mapper.OrderMapper;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private CartMapper cartMapper;
    @DubboReference
    private AddrService addrService;
    @DubboReference
    private UserService userService;
    @DubboReference
    private GoodsService goodsService;

    //生成订单
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void insert(OrderVo orderVo) throws SteduException {
        Order order = new Order();
        //生成订单id
        String orderId = IdUtil.getSnowflakeNextIdStr();
        //设置订单id
        order.setId(orderId);
        //获取地址对象
        Addr addr = addrService.selectById(orderVo.getAddrId());
        //设置地址详情
        order.setAddrDetail(addr.getContact() + " "
                + addr.getPhone() + " "
                + addr.getProvince() + " "
                + addr.getCity() + " "
                + addr.getDistrict() + " "
                + addr.getStreet() + " "
                + addr.getAddress());
        //添加订单
        order.setUserId(orderVo.getUserId());
        order.setPayType(0);
        order.setAddrId(orderVo.getAddrId());
        order.setStatus(0);
        order.setCreateTime(new Date());
        orderMapper.insert(order);

        //生成详情
        //orderVo中Integer[] cartIds每个购物车的id对应一个商品的详情
        for (Integer cartId : orderVo.getCartIds()) {
            //1.获取购物车--判断购物车是否合法
            Cart cart = cartMapper.selectById(cartId);
            if (cart == null) {
                throw new SteduException("购物车不存在,无法获取订单");
            }
            if (!cart.getUserId().equals(orderVo.getUserId())) {
                throw new SteduException("购物车不属于你本人,无法生成订单");
            }
            //2.获取商品的id
            Goods goods = goodsService.selectById(cart.getGoodsId());
            //是否存在
            if (goods == null) {
                throw new SteduException("商品不存在,无法生成订单");
            }
            if (goods.getStatus().equals(1)) {
                throw new SteduException("商品下架,无法生成订单");
            }
            //商品是否充足
            if (goods.getCount() < cart.getCount()) {
                throw new SteduException("商品库存不足,无法生成订单");
            }
            //3.减去商品的库存
            goods.setCount(goods.getCount() - cart.getCount());
            goodsService.update(goods);
            //4.添加详情
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setCount(cart.getCount());
            orderDetail.setPrice(goods.getPrice());
            orderDetail.setOrderId(orderId);
            orderDetail.setGoodsId(goods.getId());
            orderDetailMapper.insert(orderDetail);

        }
        //删除购物车--删除的是个ids数组，根据里边的id删
        cartMapper.deleteByIds(Arrays.asList(orderVo.getCartIds()));
        orderVo.setOrderId(orderId);
    }

    @Override
    public boolean delete(String id) {
        return false;
    }

    @Override
    public boolean update(Order order) {
        return orderMapper.update(order) == 1;
    }

    @Override
    public Order selectById(String id, Integer userId) throws SteduException {
        Order order = orderMapper.selectById(id);
        if (!order.getUserId().equals(userId)) {
            throw new SteduException("该订单不属于你喽");
        }
        order.setAddr(addrService.selectById(order.getAddrId()));
        order.setUser(userService.selectById(order.getUserId()));
        //查询订单详情对应的商品的信息
        for (OrderDetail orderDetail : order.getOrderDetailList()) {
            //使用dubbo去调用goodsService
            orderDetail.setGoods(goodsService.selectById(orderDetail.getGoodsId()));
        }
        return order;
    }

    //管理员用的
    @Override
    public Order selectById1(String id) throws SteduException {
        Order order = orderMapper.selectById(id);
        order.setAddr(addrService.selectById(order.getAddrId()));
        order.setUser(userService.selectById(order.getUserId()));
        //查询订单详情对应的商品的信息
        for (OrderDetail orderDetail : order.getOrderDetailList()) {
            //使用dubbo去调用goodsService
            orderDetail.setGoods(goodsService.selectById(orderDetail.getGoodsId()));
        }
        return order;
    }

    @Override
    public List<Order> selectByUserId(Integer userId) {
        return orderMapper.selectByUserId(userId);
    }

    //不用分页插件的话用Limit进行分页
    @Override
    public PageInfo<Order> selectByCondition(Order condition, Integer pageNum, Integer pageSize) {
        //设置分页参数
        PageHelper.startPage(pageNum, pageSize);
        //查询
        List<Order> orders = orderMapper.selectByCondition(condition);
        for (Order order : orders) {
            order.setUser(userService.selectById(order.getUserId()));
            order.setAddr(addrService.selectById(order.getAddrId()));
            //查询订单详情对应的商品的信息
            for (OrderDetail orderDetail : order.getOrderDetailList()) {
                //使用dubbo去调用goodsService
                orderDetail.setGoods(goodsService.selectById(orderDetail.getGoodsId()));
            }
        }
        //创建分页信息的对象
        PageInfo<Order> pageInfo = new PageInfo<>(orders);
        return pageInfo;
    }

    @com.stedu.mall.orderservice.annotation.Log(name = "订单支付记入日志")
    //支付
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void pay(OrderVo orderVo) throws SteduException {
        //根据orderId查询顶单
        Order order = orderMapper.selectById(orderVo.getOrderId());
        if (order == null) {
            throw new SteduException("订单不存在，无法支付");
        }
        if (!order.getUserId().equals(orderVo.getUserId())) {
            throw new SteduException("订单不属于你，无法支付");
        }
        if (!order.getStatus().equals(0)) {
            throw new SteduException("订单状态错误，无法支付");
        }
        //设置status为1--已支付
        order.setStatus(1);
        //设置payType为0--余额支付
        order.setPayType(0);
        //更新订单
        orderMapper.update(order);

        //根据用户id查询用户
        User user = userService.selectById(orderVo.getUserId());
        //判断支付密码是否存在是否正确
        String payPassword = user.getPayPassword();
        if (payPassword == null) {
            throw new SteduException("没有设置支付密码，快去设置叭");
        }
        //对用户输入的支付密码进行加密
        String md5 = SecureUtil.md5(SecureUtil.md5(orderVo.getPayPassword() + user.getSalt()));
        if (!md5.equals(payPassword)) {
            throw new SteduException("支付密码错误，请重试一边");
        }
        //计算当前订单的总金额 orderDetail 数量*单价
        BigDecimal sum = new BigDecimal(0);
        for (OrderDetail orderDetail : order.getOrderDetailList()) {
            BigDecimal price = orderDetail.getPrice();
            Integer count = orderDetail.getCount();
            BigDecimal multiply = price.multiply(new BigDecimal(count));
            sum = sum.add(multiply);
        }

        //判断余额是否充足
        // BigDecimal如何比较大小  java的比较器
        if (user.getMoney().compareTo(sum) < 0) {
            throw new SteduException("余额不足，买不起0.0");
        }

        //扣除余额
        User u = new User();
        u.setId(orderVo.getUserId());
        u.setMoney(user.getMoney().subtract(sum));
        userService.update(u, orderVo.getUserId());
    }

    @com.stedu.mall.orderservice.annotation.Log(name = "订单支付记入日志")
    //支付
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void pay1(OrderVo orderVo) throws SteduException {
        //根据orderId查询顶单
        Order order = orderMapper.selectById(orderVo.getOrderId());
        if (order == null) {
            throw new SteduException("订单不存在，无法支付");
        }
        if (!order.getUserId().equals(orderVo.getUserId())) {
            throw new SteduException("订单不属于你，无法支付");
        }
        if (!order.getStatus().equals(0)) {
            throw new SteduException("订单状态错误，无法支付");
        }
        //设置status为1--已支付
        order.setStatus(1);
        //设置payType为0--支付宝支付
        order.setPayType(1);
        //更新订单
        orderMapper.update(order);
    }

    //用户申请退款
    @Override
    public void updateMoney(Order order) {
        order.setStatus(6);
        orderMapper.update(order);
    }

    //给用户退款
    @Override
    public void updateMoney1(String id) throws SteduException {
        Order order = selectById1(id);
        User user1 = userService.selectById(order.getUserId());
        BigDecimal sum = new BigDecimal("0");
        for (OrderDetail orderDetail : order.getOrderDetailList()) {
            BigDecimal count = new BigDecimal(orderDetail.getCount());
            BigDecimal price = orderDetail.getPrice();
            sum = sum.add(price.multiply(count));
        }
        //返还余额 update
        User u = new User();
        u.setId(order.getUserId());
        u.setMoney(user1.getMoney().add(sum));
        userService.update1(u, order.getUserId());
        order.setStatus(10);
        orderMapper.update(order);
    }

    //用户申请退货退款
    @Override
    public void updateGoodsMoney(Order order) {
        order.setStatus(4);
        orderMapper.update(order);
    }

    //给用户退货退款
    @Override
    public void updateGoodsMoney1(String id) throws SteduException {
        Order order = selectById1(id);
        User user1 = userService.selectById(order.getUserId());
        BigDecimal sum = new BigDecimal("0");
        for (OrderDetail orderDetail : order.getOrderDetailList()) {
            Goods goods = goodsService.selectById(orderDetail.getGoodsId());
            goods.setCount(goods.getCount()+orderDetail.getCount());
            goodsService.update(goods);
            BigDecimal count = new BigDecimal(orderDetail.getCount());
            BigDecimal price = orderDetail.getPrice();
            sum = sum.add(price.multiply(count));
        }
        //返还余额 update
        User u = new User();
        u.setId(order.getUserId());
        u.setMoney(user1.getMoney().add(sum));
        userService.update1(u, order.getUserId());
        order.setStatus(9);
        orderMapper.update(order);
    }
}
